﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ShredTheLog.Api;
using System.Windows.Input;
using ShredTheLog.Common.MVVM;
using System.ComponentModel.Composition;
using ShredTheLog.Converters;
using System.Windows.Media;
using System.Windows;
using ShredTheLog.Views;
using ShredTheLog.ViewModels;
using System.Diagnostics.Contracts;
using ShredTheLog.Controls;

namespace ShredTheLog.Plugins
{
    public sealed class JoinPublicChatRoomCommands
    {
        public const string BiLingual = "BiLingual";
        public const string MonoLingual = "MonoLingual";
        public const string Other = "Other";

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 0, Group = BiLingual)]
        public IUiCommand JoinEnglishSpanishRoomCommand = new JoinBiLingualRoomCommand(Language.English, Language.Spanish);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 100, Group = BiLingual)]
        public IUiCommand JoinEnglishJapaneseRoomCommand = new JoinBiLingualRoomCommand(Language.English, Language.Japanese);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 200, Group = BiLingual)]
        public IUiCommand JoinEnglishPortugueseRoomCommand = new JoinBiLingualRoomCommand(Language.English, Language.Portuguese);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 300, Group = BiLingual)]
        public IUiCommand JoinEnglishChineseMandarinRoomCommand = new JoinBiLingualRoomCommand(Language.English, Language.ChineseMandarin);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 400, Group = BiLingual)]
        public IUiCommand JoinEnglishRussianRoomCommand = new JoinBiLingualRoomCommand(Language.English, Language.Russian);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 500, Group = BiLingual)]
        public IUiCommand JoinEnglishFrenchRoomCommand = new JoinBiLingualRoomCommand(Language.English, Language.French);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 600, Group = BiLingual)]
        public IUiCommand JoinEnglishKoreanRoomCommand = new JoinBiLingualRoomCommand(Language.English, Language.Korean);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 700, Group = BiLingual)]
        public IUiCommand JoinEnglishArabicRoomCommand = new JoinBiLingualRoomCommand(Language.English, Language.Arabic);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 800, Group = BiLingual)]
        public IUiCommand JoinEnglishItalianRoomCommand = new JoinBiLingualRoomCommand(Language.English, Language.Italian);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 900, Group = BiLingual)]
        public IUiCommand JoinEnglishGermanRoomCommand = new JoinBiLingualRoomCommand(Language.English, Language.German);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 1000, Group = BiLingual)]
        public IUiCommand JoinEnglishTurkishRoomCommand = new JoinBiLingualRoomCommand(Language.English, Language.Turkish);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 1100, Group = MonoLingual)]
        public IUiCommand JoinEnglishRoomCommand = new JoinMonoLingualRoomCommand(Language.English);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 1200, Group = MonoLingual)]
        public IUiCommand JoinSpanishRoomCommand = new JoinMonoLingualRoomCommand(Language.Spanish);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 1300, Group = MonoLingual)]
        public IUiCommand JoinFrenchRoomCommand = new JoinMonoLingualRoomCommand(Language.French);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 1400, Group = MonoLingual)]
        public IUiCommand JoinJapaneseRoomCommand = new JoinMonoLingualRoomCommand(Language.Japanese);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 1500, Group = MonoLingual)]
        public IUiCommand JoinGermanRoomCommand = new JoinMonoLingualRoomCommand(Language.German);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 1600, Group = MonoLingual)]
        public IUiCommand JoinItalianRoomCommand = new JoinMonoLingualRoomCommand(Language.Italian);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 1700, Group = MonoLingual)]
        public IUiCommand JoinChineseMandarinRoomCommand = new JoinMonoLingualRoomCommand(Language.ChineseMandarin);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 1800, Group = MonoLingual)]
        public IUiCommand JoinRussianRoomCommand = new JoinMonoLingualRoomCommand(Language.Russian);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 1900, Group = MonoLingual)]
        public IUiCommand JoinPortugueseRoomCommand = new JoinMonoLingualRoomCommand(Language.Portuguese);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 2000, Group = MonoLingual)]
        public IUiCommand JoinArabicRoomCommand = new JoinMonoLingualRoomCommand(Language.Arabic);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 2100, Group = MonoLingual)]
        public IUiCommand JoinKoreanRoomCommand = new JoinMonoLingualRoomCommand(Language.Korean);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 2200, Group = MonoLingual)]
        public IUiCommand JoinHindiRoomCommand = new JoinMonoLingualRoomCommand(Language.Hindi);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 2300, Group = MonoLingual)]
        public IUiCommand JoinChineseCantoneseRoomCommand = new JoinMonoLingualRoomCommand(Language.ChineseCantonese);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 2400, Group = MonoLingual)]
        public IUiCommand JoinDutchRoomCommand = new JoinMonoLingualRoomCommand(Language.Dutch);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 2500, Group = MonoLingual)]
        public IUiCommand JoinTurkishRoomCommand = new JoinMonoLingualRoomCommand(Language.Turkish);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 2600, Group = MonoLingual)]
        public IUiCommand JoinSwedishRoomCommand = new JoinMonoLingualRoomCommand(Language.Swedish);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 2700, Group = MonoLingual)]
        public IUiCommand JoinThaiRoomCommand = new JoinMonoLingualRoomCommand(Language.Thai);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 2800, Group = MonoLingual)]
        public IUiCommand JoinPolishRoomCommand = new JoinMonoLingualRoomCommand(Language.Polish);

        [Export(typeof(ICommandListItem))]
        [MenuCommandMetadata(Menu = Menus.Rooms, Order = 2900, Group = MonoLingual)]
        public IUiCommand JoinHungarianRoomCommand = new JoinMonoLingualRoomCommand(Language.Hungarian);
    }

    [ContractClass(typeof(JoinPublicChatRoomCommand_Contract))]
    public abstract class JoinPublicChatRoomCommand : DelegateCommand, IUiCommand
    {
        [Import]
        private IShredServices ShredServices { get; set; }

        public string Name 
        { 
            get 
            { 
                string result = RoomConverter.Default.Convert(RoomName);
                Contract.Assume(!String.IsNullOrWhiteSpace(result));
                return result;
            } 
        }
        public abstract ImageSource Image { get; }
        protected abstract string RoomName { get; }

        protected JoinPublicChatRoomCommand()
        {
            Globals.CompositionContainer.SatisfyImportsOnce(this);

            _executeMethod =
                () =>
                {
                    ShredServices.OpenTextChatRoom(RoomName);
                };
            _canExecuteMethod = () => ShredServices.TextChat != null;
        }
    }

    [ContractClassFor(typeof(JoinPublicChatRoomCommand))]
    internal abstract class JoinPublicChatRoomCommand_Contract : JoinPublicChatRoomCommand
    {
        public override ImageSource Image
        {
            get { throw new NotImplementedException(); }
        }

        protected override string RoomName
        {
            get 
            {
                Contract.Ensures(!String.IsNullOrWhiteSpace(Contract.Result<string>()));
                throw new NotImplementedException(); 
            }
        }
    }

    public sealed class JoinMonoLingualRoomCommand : JoinPublicChatRoomCommand
    {
        public JoinMonoLingualRoomCommand(Language language)
        {
            Language = language;
        }
        public Language Language { get; private set; }
        protected override string RoomName 
        { 
            get 
            { 
                string result = String.Format("{0}{1}", RoomConverter.PublicRoomPrefix, RoomConverter.LanguageCodes[Language]);
                Contract.Assume(!String.IsNullOrWhiteSpace(result));
                return result;
            } 
        }
        public override ImageSource Image { get { return FlagConverter.Convert(Language); } }
    }

    public sealed class JoinBiLingualRoomCommand : JoinPublicChatRoomCommand
    {
        public JoinBiLingualRoomCommand(Language language1, Language language2)
        {
            Language1 = language1;
            Language2 = language2;
        }
        public Language Language1 { get; private set; }
        public Language Language2 { get; private set; }
        protected override string RoomName 
        { 
            get 
            {
                string result = String.Format("{0}{1}{2}", RoomConverter.PublicRoomPrefix, RoomConverter.LanguageCodes[Language1], RoomConverter.LanguageCodes[Language2]);
                Contract.Assume(!String.IsNullOrWhiteSpace(result));
                return result;
            } 
        }
        public override ImageSource Image 
        { 
            get 
            {
                var dg = new DrawingGroup();
                dg.Children.Add(new ImageDrawing(FlagConverter.Convert(Language1), new Rect(0, 0, 150, 100)));
                dg.Children.Add(new ImageDrawing(FlagConverter.Convert(Language2), new Rect(75, 50, 150, 100)));
                return new DrawingImage(dg); 
            } 
        }
    }

    [Export(typeof(ICommandListItem))]
    [MenuCommandMetadata(Menu = Menus.Rooms, Order = 3000, Group = JoinPublicChatRoomCommands.Other)]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class JoinOtherRoomCommand : JoinPublicChatRoomCommand
    {
        [Import]
        private IShredServices ShredServices { get; set; }

        protected override string RoomName { get { return RoomConverter.OtherRoomID; } }
        public override ImageSource Image { get { return FlagConverter.DefaultFlag; } }
    }

    [Export(typeof(ICommandListItem))]
    [MenuCommandMetadata(Menu = Menus.Rooms, Order = 3100, Group = JoinPublicChatRoomCommands.Other)]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class JoinScandinavianRoomCommand : JoinPublicChatRoomCommand
    {
        [Import]
        private IShredServices ShredServices { get; set; }

        protected override string RoomName { get { return RoomConverter.ScandinavianRoomID; } }
        public override ImageSource Image { get { return FlagConverter.ScandinavianFlag; } }
    }
}
